<?php

namespace app\api\controller;

use app\facade\Redis;
use app\models\{User as Users, Money, Quotes, Price, Order, UserAuth, Contack, Prelist, Myprelist, Teamcode, Wallet, Moneylog, Config, Withdraw};
use think\Facade\Config as Configs;
use app\facade\Mns;
use app\facade\Eth;
use app\facade\Btc;
use think\Validate;
use think\Db;

use function PHPSTORM_META\map;

class User extends Base
{
    //注册账号
    private $url = 'https://api-aws.huobi.pro/';
    public function register()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'type' => 'require|in:1,2',
            'account' => 'require',
            'code' => 'require',
            'password' => 'require',
            'trade' => 'require',
        ], [
            'type.require' => '账号类型不能为空',
            'type.in' => '账号类型错误',
            'account.require' => '账号不能为空',
            'code.require' => '验证码必须填写',
            'password.require' => '登录密码必须填写',
            'trade.require' => '交易密码不许填写',
        ]);
        if (!$validate->check($data)) {
            $this->result([], 1, $validate->getError());
        }
        //识别验证码是否正确
        switch ($data['type']) {
            case '1':
                if (empty($data['country'])) {
                    $this->result([], 1, '国家区号不能为空');
                }
                $data['email'] = '';
                $data['mobile'] = trim($data['account']);
                //查找账号是否已存在
                $haveuser = (new Users())->where(['country' => $data['country'], 'mobile' => $data['account']])->find();
                if (!empty($haveuser)) {
                    $this->result([], 1, '手机账号已存在');
                }
                //验证手机验证码
                $mns = (new Mns())->checkCode($data['code'], $data['country'] . $data['account'], $data['type']);
                if (!$mns) {
                    $this->result([], 1, '手机验证码验证失败');
                }
                break;
            case '2':
                $data['email'] = trim($data['account']);
                $data['country'] = '';
                $data['mobile'] = '';
                if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
                    $this->result([], 1, '邮箱格式错误');
                }
                //查找账号是否已存在
                $haveuser = (new Users())->where(['email' => $data['account']])->find();
                if (!empty($haveuser)) {
                    $this->result([], 1, '邮箱账号已存在');
                }
                $mns = (new Mns())->checkCode($data['code'], $data['country'], $data['type']);
                if (!$mns) {
                    $this->result([], 1, '邮箱验证码验证失败');
                }
                break;
            default:
                $this->result([], 1, '类型错误');
                break;
        }
        $pid = 0;
        if (!empty($data['invite'])) {
            $puser = (new Users())->where('code', $data['invite'])->find();
            if (empty($puser)) {
                $this->result([], 1, '推荐人不存在');
            }
            $pid = $puser['id'];
        }
        $coin = Configs::get('config.coins');
        $code = recode(new Users());
        $token = md5(md5($code . time()));
        $save = [
            'type' => $data['type'],
            'country' => $data['country'],
            'mobile' =>  $data['mobile'],
            'email' =>  $data['email'],
            'password' =>  md5(md5($data['password'])),
            'trade' =>  md5(md5($data['trade'])),
            'code' => $code,
            'pid' => $pid,
            'token' => $token
        ];
        $moneysave = [];

        Db::startTrans();
        try {
            $uid = (new Users())->insertGetId($save);
            foreach ($coin as $k => $v) {
                $moneysave[] = [
                    'user_id' => $uid,
                    'type' => $k
                ];
            }
            if (!empty($moneysave)) {
                (new Money())->saveAll($moneysave);
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->result($e->getMessage(), 1, '注册失败，请重试');
        }
        $this->result(['token' => $token], 0, '注册成功');
    }

    //账号登录
    public function Login()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'type' => 'require|in:1,2',
            'account' => 'require',
            'code' => 'require',
            'password' => 'require'
        ], [
            'type.require' => '账号类型不能为空',
            'type.in' => '账号类型错误',
            'account.require' => '账号不能为空',
            'code.require' => '验证码必须填写',
            'password.require' => '登录密码必须填写'
        ]);
        if (!$validate->check($data)) {
            $this->result([], 1, $validate->getError());
        }
        switch ($data['type']) {
            case '1':
                if (empty($data['country'])) {
                    $this->result([], 1, '国家区号不能为空');
                }
                //查找账号是否已存在
                $user = (new Users())->where(['country' => $data['country'], 'mobile' => $data['account'], 'password' => md5(md5($data['password']))])->find();
                if (empty($user)) {
                    $this->result([], 1, '手机账号不存在或密码错误');
                }
                //验证手机验证码
                $mns = (new Mns())->checkCode($data['code'], $data['country'] . $data['account'], $data['type']);
                if (!$mns) {
                    $this->result([], 1, '手机验证码验证失败');
                }
                break;
            case '2':
                //查找账号是否已存在
                $user = (new Users())->where(['email' => $data['account'], 'password' => md5(md5($data['password']))])->find();
                if (empty($user)) {
                    $this->result([], 1, '邮箱账号不存在或密码错误');
                }
                $mns = (new Mns())->checkCode($data['code'], $data['country']);
                if (!$mns) {
                    $this->result([], 1, '邮箱验证码验证失败');
                }
                break;
            default:
                $this->result([], 1, '类型错误');
                break;
        }
        if (!empty($user)) {
            $token = md5(md5($user['id'] . $user['code'] . time()));
            (new Users())->where('id', $user['id'])->update(['token' => $token]);
            Redis::setex($token, 86400 * 5, $user['id']);
            $this->result(['token' => $token], 0, '登录成功');
        }
        $this->result([], 1, '账号不存在或密码错误');
    }

    public function Forget()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'type' => 'require|in:1,2',
            'account' => 'require',
            'code' => 'require',
            'password' => 'require',
            'logintype' => 'require|in:1,2'
        ], [
            'type.require' => '账号类型不能为空',
            'type.in' => '账号类型错误',
            'account.require' => '账号不能为空',
            'code.require' => '验证码必须填写',
            'password.require' => '更改密码必须填写',
            'logintype.require' => '登录类型不能为空',
            'logintype.in' => '登录类型错误'
        ]);
        if (!$validate->check($data)) {
            $this->result([], 1, $validate->getError());
        }
        switch ($data['type']) {
            case '1':
                if (empty($data['country'])) {
                    $this->result([], 1, '国家区号不能为空');
                }
                //查找账号是否已存在
                $user = (new Users())->where(['country' => $data['country'], 'mobile' => $data['account']])->find();
                if (empty($user)) {
                    $this->result([], 1, '手机账号不存在');
                }
                //验证手机验证码
                $mns = (new Mns())->checkCode($data['code'], $data['country'] . $data['account'], $data['type']);
                if (!$mns) {
                    $this->result([], 1, '手机验证码验证失败');
                }
                break;
            case '2':
                //查找账号是否已存在
                $user = (new Users())->where(['email' => $data['account']])->find();
                if (empty($user)) {
                    $this->result([], 1, '邮箱账号不存在或密码错误');
                }
                $mns = (new Mns())->checkCode($data['code'], $data['country'], $data['type']);
                if (!$mns) {
                    $this->result([], 1, '邮箱验证码验证失败');
                }
                break;
            default:
                $this->result([], 1, '类型错误');
                break;
        }
        if (!empty($user)) {
            $password = md5(md5($data['password']));
            switch ($data['logintype']) {
                case '1':
                    if ($password == $user['password']) {
                        $this->result([], 0, '修改密码与原密码相同');
                    }
                    $res = (new Users())->where('id', $user['id'])->update(['password' => $password]);
                    if ($res) {
                        $this->result([], 0, '修改成功');
                    }
                    break;
                case '2':
                    if ($password == $user['trade']) {
                        $this->result([], 0, '修改密码与原密码相同');
                    }
                    $res = (new Users())->where('id', $user['id'])->update(['trade' => $password]);
                    if ($res) {
                        $this->result([], 0, '修改成功');
                    }
                    break;
                default:
                    $this->result([], 1, '类型错误');
                    break;
            }
        }
        $this->result([], 1, '修改失败');
    }

    //发布订单
    public function Cointrading()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'id' => 'require',
            'type' => 'require|in:1,2',
            'prmoney' => 'require|in:1,2',
            'commnum' => 'require',
            'commprice' => 'require',
            'commtotal' => 'require',
        ], [
            'id.require' => '交易ID必须上传',
            'type.require' => '买卖类型必须选择',
            'type.in' => '买卖类型范围不正确',
            'prmoney.require' => '交易类型必须选择',
            'prmoney.in' => '交易类型范围不正确',
            'commnum.require' => '委托数量必须选择',
            'commprice.require' => '委托单价必须选择',
            'commtotal.require' => '委托总额必须选择',
        ]);
        if (!$validate->check($data)) {
            $this->result([], 1, $validate->getError());
        }
        $quotes = (new Quotes())->where('id', $data['id'])->find();
        if (empty($quotes) || $quotes['istrans'] != 1) {
            $this->result([], 1, '交易对不存在或不可交易');
        }
        $user_id = $this->request->user_id;
        $user = $this->request->user;
        $coinnum = 0; //交易币种数量
        $martnum = 0; //市场币种数量
        $coin = Configs::get('config.coins.' . $quotes['coin']);
        $mart = Configs::get('config.coins.' . $quotes['mart']);
        //限价对数据进行计算
        if ($data['prmoney'] == '1') {
            /*挂单价格判断代码start */
            if ($quotes['coin'] == 1) {
                $price = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $quotes['coin'], 'mart' => $quotes['mart'], 'istrue' => 1])->order('dates desc')->value('price');
                if (empty($price)) {
                    $this->result([], 1, '币种价格未确定');
                }
            }
            /*
                 * 挂单价格判断代码end
                 */
            if ($data['type'] == 1) {
                //代码块
                if ($data['commprice'] <= 0) {
                    $this->result([], 1, '委托单价必须大于0');
                }
                if ($data['commtotal'] <= 0) {
                    $this->result([], 1, '委托总额必须大于0');
                }
                $martnum = $data['commtotal'];
                $data['commnum'] = floor($data['commtotal'] * 1000000 / $data['commprice']) / 1000000;
            } else {
                //代码块
                if ($data['commprice'] <= 0) {
                    $this->result([], 1, '委托单价必须大于0');
                }
                if ($data['commnum'] <= 0) {
                    $this->result([], 1, '委托数量必须大于0');
                }
                $coinnum = $data['commnum'];
                $data['commtotal'] = $data['commprice'] * $data['commnum']; //预交委托总价
            }
        } else {
            $data['commprice'] = 0;
            if ($data['type'] == 1) {
                //代码块
                if ($data['commtotal'] <= 0) {
                    $this->result([], 1, '委托总额必须大于0');
                }
                $martnum = $data['commtotal'];
                $data['commnum'] = 0;
            } else {
                //代码块
                if ($data['commnum'] <= 0) {
                    $this->result([], 1, '委托数量必须大于0');
                }
                $coinnum = $data['commnum'];
                $data['commtotal'] = $data['commprice'] * $data['commnum']; //预交委托总价
            }
        }
        if ($coinnum <= 0 && $martnum <= 0) {
            $this->result([], 1, '参数错误');
        }
        //判断币种是否足够
        if ($coinnum > 0) {
            $coinmoney = (new Money())->where(['user_id' => $user_id, 'type' => $quotes['coin']])->find();
            if ($coinmoney['money'] < $coinnum) {
                $this->result([], 1, $coin . '不足，请充值后交易');
            }
        }
        if ($martnum > 0) {
            $martmoney = (new Money())->where(['user_id' => $user_id, 'type' => $quotes['mart']])->find();
            if ($martmoney['money'] < $martnum) {
                $this->result([], 1, $mart . '不足，请充值后交易');
            }
        }
        $data['user_id'] = $user_id;
        $data['coin'] = $quotes['coin'];
        $data['mart'] = $quotes['mart'];
        $data['todays'] = date('Y-m-d');
        Db::startTrans();
        try {
            if ($coinnum > 0) {
                (new Money())->MoneyEdit($coinmoney, 0, -$coinnum, 1, '发布币币交易', 0, 0);
                (new Money())->where(['id' => $coinmoney['id'], 'fmoney' => $coinmoney['fmoney']])
                    ->setInc('fmoney', $coinnum);
            }
            if ($martnum > 0) {
                (new Money())->MoneyEdit($martmoney, 0, -$martnum, 1, '发布币币交易', 0, 0);
                (new Money())->where(['id' => $martmoney['id'], 'fmoney' => $martmoney['fmoney']])
                    ->setInc('fmoney', $martnum);
            }
            unset($data['id']);
            (new Order())->allowField(true)->save($data);
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            dump($e->getMessage());
            Db::rollback();
            $this->result([], 1, '发布失败，请稍后重试');
        }
        $this->result([], 0, '发布成功');
    }


    public function Mytodayorder()
    {
        $status = $this->request->get('status/d', 0);
        $list = (new Order())->field('user_id,clostime', true);
        if (!empty($status)) {
            $list = $list->where('status', $status);
        }
        $list = $list->where('user_id', $this->request->user_id)->order('status asc,id desc')->paginate(20, false, ['query' => $this->request->param()]);
        foreach ($list as $lists) {
            $lists['coin'] = Configs::get('config.coins.' . $lists['coin']);
            $lists['mart'] = Configs::get('config.coins.' . $lists['mart']);
        }
        $this->result($list, 0, '查询完成');
    }


    public function Ordercacel()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'id' => 'require',
        ], [
            'id.require' => '订单ID必须填写传',
        ]);
        if (!$validate->check($data)) {
            $this->result([], 1, $validate->getError());
        }
        $user_id = $this->request->user_id;
        $order = (new Order())->where(['id' => $data['id'], 'user_id' => $user_id])->find();
        if (empty($order) || $order['status'] != 1) {
            $this->result([], 1, '订单不存在或不可取消');
        }
        $coinnum = 0; //交易币种数量
        $martnum = 0; //市场币种数量
        //计算返回币种数量和类型
        if ($order['type'] == 1) {
            $martnum = $order['commtotal'] - $order['transtotal'];
            $martmoney = (new Money())->where(['user_id' => $user_id, 'type' => $order['mart']])->find();
        } else {
            $coinnum = $order['commnum'] - $order['transnum'];
            $coinmoney = (new Money())->where(['user_id' => $user_id, 'type' => $order['coin']])->find();
        }
        Db::startTrans();
        try {
            (new Order())->where(['id' => $order['id'], 'status' => 1])->update(['status' => 3]); //取消订单
            if ($coinnum > 0) {
                (new Money())->MoneyEdit($coinmoney, 0, $coinnum, 2, '取消币币交易', 0, 0);
                (new Money())->where(['id' => $coinmoney['id'], 'fmoney' => $coinmoney['fmoney']])
                    ->setDec('fmoney', $coinnum);
            }
            if ($martnum > 0) {
                (new Money())->MoneyEdit($martmoney, 0, $martnum, 2, '取消币币交易', 0, 0);
                (new Money())->where(['id' => $martmoney['id'], 'fmoney' => $martmoney['fmoney']])
                    ->setDec('fmoney', $martnum);
            }
            Db::commit();
        } catch (\Exception $e) {
            dump($e->getMessage());
            // 回滚事务
            Db::rollback();
            $this->result([], 1, '取消失败，请稍后重试');
        }
        $this->result([], 0, '取消成功');
    }

    public function Money()
    {
        $list =  (new Money())->field('money,type,fmoney')->where('user_id', $this->request->user_id)->select();
        $coinstype = Configs::get('config.coins');
        foreach ($list as $lists) {
            $lists['name'] = $coinstype[$lists['type']];
            if ($lists['type'] == 1) {
                $price = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $lists['type'], 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price') ?? 0;
            } elseif ($lists['name'] == 'USDT') {
                $price = 1;
            } else {
                $url = $this->url . "market/trade?symbol=" . strtolower($lists['name'] . 'USDT');
                $result = api_curl($url);
                $client = json_decode($result, true);
                $price = 0;
                if (!empty($client['status']) && $client['status'] == 'ok') {
                    $price = $client['tick']['data'][0]['price'];
                }
            }
            $lists['price'] = $price;
            $lists['total'] = ($lists['money'] + $lists['fmoney']) * $price;
        }
        $this->result($list, 0, '查询完成');
    }

    public function UserAuth()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            $validate = new Validate([
                'name' => 'require',
                'cards' => 'require',
                'obverse' => 'require',
                'rbverse' => 'require',
                'orverse' => 'require',
            ], [
                'name.require' => '姓名必须填写',
                'cards.require' => '身份证号必须填写',
                'obverse.require' => '身份证正面必须填写',
                'rbverse.require' => '身份证反面必须填写',
                'orverse.require' => '身份证手持必须填写',
            ]);
            if (!$validate->check($data)) {
                $this->result([], 1, $validate->getError());
            }
            $userauth = (new UserAuth())->where('user_id', $this->request->user_id)->find();
            if ($userauth && $userauth['status'] == 2) {
                $this->result([], 1, '您已认证成功，无需重复认证');
            }
            $data['status'] = 1;
            $data['user_id'] = $this->request->user_id;
            Db::startTrans();
            try {
                if ($userauth) {
                    (new UserAuth())->save($data, ['user_id' => $this->request->user_id]);
                } else {
                    (new UserAuth())->save($data);
                }
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                dump($e->getMessage());
                Db::rollback();
                $this->result([], 1, '提交失败，请稍后重试');
            }
            $this->result([], 0, '提交成功');
        } else {
            $userauth = (new UserAuth())->where('user_id', $this->request->user_id)->find();
            $this->result($userauth, 0, '获取成功');
        }
    }

    public function Contack()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            $validate = new Validate([
                'infos' => 'require',
            ], [
                'infos.require' => '反馈内容必须填写',
            ]);
            if (!$validate->check($data)) {
                $this->result([], 1, $validate->getError());
            }
            $data['user_id'] = $this->request->user_id;
            $res = (new Contack())->allowField(true)->save($data);
            if ($res) {
                $this->result([], 0, '提交成功');
            }
            $this->result([], 1, '提交失败');
        } else {
            $list = (new Contack())->order('id desc')->where('user_id', $this->request->user_id)->field('id,user_id', true)->paginate(20, false, ['query' => $this->request->param()]);
            foreach ($list as $lists) {
                $lists['images'] = json_decode($lists['images'], true);
            }
            $this->result($list, 0, '获取成功');
        }
    }

    public function info()
    {
        $user = $this->request->user;
        $user['share'] = '';
        unset($user['password']);
        unset($user['trade']);
        unset($user['token']);
        unset($user['pid']);
        unset($user['updated']);
        $this->result($user, 0, '获取成功');
    }

    public function  prelist()
    {
        $status = $this->request->get('status/d', '');
        $list = (new Prelist())->order('id desc');
        if ($status) {
            $list = $list->where('status', $status);
        }
        $list = $list->field('id,title,images,target,coin,day,status,starttime,video')->select();
        foreach ($list as $lists) {
            $lists['endtime'] = date('Y-m-d H:i:s', strtotime($lists['starttime']) + 86400 * $lists['day']); //结束时间
            $lists['time'] =  strtotime($lists['starttime']) + 86400 * $lists['day'] - time();
            $lists['time'] = $lists['time'] > 0 ? $lists['time'] : 0;
            $lists['time'] = $lists['status'] == 1 ? $lists['time'] : 0;
            $lists['coinname'] = Configs::get('config.coins')[$lists['coin']] ?? '';
            if ($status == 1 && $lists['endtime'] < date('Y-m-d H:i:s')) {
                (new Prelist())->where('id', $lists['id'])->update(['status' => 2]);
            }
        }
        $this->result($list, 0, '获取成功');
    }

    public function Prelist_detail()
    {
        $id = $this->request->get('id/d', 0);
        $result = (new Prelist())->field('id,title,images,target,coin,day,status,starttime,video,coinhave,info,conditions')->where('id', $id)->find();
        if ($result) {
            $result['endtime'] = date('Y-m-d H:i:s', strtotime($result['starttime']) + 86400 * $result['day']); //结束时间
            $result['time'] =  strtotime($result['starttime']) + 86400 * $result['day'] - time();
            $result['time'] = $result['time'] > 0 ? $result['time'] : 0;
            $result['time'] = $result['status'] == 1 ? $result['time'] : 0;
            $coins = Configs::get('config.coins');
            $result['coinname'] = $coins[$result['coin']] ?? '';
            if ($result['status'] == 1 && $result['endtime'] < date('Y-m-d H:i:s')) {
                (new Prelist())->where('id', $result['id'])->update(['status' => 2]);
            }
            $result['coinhave'] = array_filter(explode(',', $result['coinhave']));
            $result['coinprice'] = 0;
            if ($result['coin'] == 1) {
                $price = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $result['coin'], 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price') ?? 0;
            } elseif ($result['coinname'] == 'USDT') {
                $price = 1;
            } else {
                $url = $this->url . "market/trade?symbol=" . strtolower($result['coinname'] . 'USDT');
                $result = api_curl($url);
                $client = json_decode($result, true);
                if (!empty($client['status']) && $client['status'] == 'ok') {
                    $price = $client['tick']['data'][0]['price'] ?? 0;
                }
            }
            $result['coinprice'] = $price ?? 0;
            $coinlist = [];
            foreach ($result['coinhave'] as $coinhave) {
                $price1 = 0;
                if ($coinhave == 1) {
                    $price1 = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $coinhave, 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price') ?? 0;
                } elseif ($coins[$coinhave] == 'USDT') {
                    $price1 = 1;
                } else {
                    $url = $this->url . "market/trade?symbol=" . strtolower($coins[$coinhave] . 'USDT');
                    $resulturl = api_curl($url);
                    $client = json_decode($resulturl, true);
                    if (!empty($client['status']) && $client['status'] == 'ok') {
                        $price1 = $client['tick']['data'][0]['price'] ?? 0;
                    }
                }
                $propor = 0;
                if ($price > 0) {
                    $propor = floor($price1 * 10000 / $price) / 10000;
                }
                $coinlist[] = [
                    'name' => $coins[$coinhave] ?? '',
                    'propor' => $propor,
                    'cointype' => $coinhave
                ];
            }
            unset($result['coinhave']);
            $result['coinlist'] = $coinlist;
        }
        $this->result($result, 0, '获取成功');
    }

    public function Myprelist()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            $validate = new Validate([
                'id' => 'require',
                'cointype' => 'require',
                'num' => 'require|gt:0|float',
                'trade' => 'require',
                'code' => 'require'
            ], [
                'id.require' => '项目ID不能为空',
                'cointype.require' => '参与币种类型不能为空',
                'num.require' => '参与数量不能为空',
                'num.gt' => '参与数量必须大于0',
                'num.float' => '参与数量必须是数字',
                'trade.require' => '交易密码不能为空',
                'code.require' => '邀请码不能为空',
            ]);
            if (!$validate->check($data)) {
                $this->result([], 1, $validate->getError());
            }
            $result = (new Prelist())->where(['id' => $data['id'], 'status' => 1])->find();
            if (!$result) {
                $this->result([], 1, '项目不存在或已结束');
            }
            $result['coinhave'] = array_filter(explode(',', $result['coinhave']));
            if (!in_array($data['cointype'], $result['coinhave'])) {
                $this->result([], 1, '参与币种类型不在项目范围内');
            }
            $code = (new Teamcode())->where('code', $data['code'])->find();
            if (!$code) {
                $this->result([], 1, '邀请码错误');
            }
            $user = $this->request->user;
            if (md5(md5($data['trade'])) != $user['trade']) {
                $this->result([], 1, '交易密码错误');
            }
            $money = (new Money())->where(['user_id' => $user['id'], 'type' => $data['cointype']])->find();
            $money2 = (new Money())->where(['user_id' => $user['id'], 'type' => $result['coin']])->find();
            if (!$money || !$money2) {
                $this->result([], 1, '钱包错误');
            }
            if ($money['money'] < $data['num']) {
                $this->result([], 1, '参与币种数目不足');
            }
            //换算兑换比例
            $coins = Configs::get('config.coins');
            $price1 = 0;
            $price = 0;
            if ($data['cointype'] == 1) {
                $price1 = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $data['cointype'], 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price') ?? 0;
            } elseif ($coins[$data['cointype']] == 'USDT') {
                $price1 = 1;
            } else {
                $url = $this->url . "market/trade?symbol=" . strtolower($coins[$data['cointype']] . 'USDT');
                $resulturl = api_curl($url);
                $client = json_decode($resulturl, true);
                if (!empty($client['status']) && $client['status'] == 'ok') {
                    $price1 = $client['tick']['data'][0]['price'] ?? 0;
                }
            }
            if ($result['coin'] == 1) {
                $price = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $result['coin'], 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price') ?? 0;
            } elseif ($coins[$result['coin']] == 'USDT') {
                $price = 1;
            } else {
                $url = $this->url . "market/trade?symbol=" . strtolower($coins[$result['coin']] . 'USDT');
                $resulturl = api_curl($url);
                $client = json_decode($resulturl, true);
                if (!empty($client['status']) && $client['status'] == 'ok') {
                    $price = $client['tick']['data'][0]['price'] ?? 0;
                }
            }
            if ($price <= 0 || $price1 <= 0) {
                $this->result([], 1, '系统价格变化频繁，请稍后再试');
            }
            //兑换数量
            $coinnum =  floor($data['num'] * $price1 * 10000 / $price) / 10000;
            Db::startTrans();
            try {
                (new Money())->MoneyEdit($money, 0, -$data['num'], 3, '项目兑换', 0, 0);
                (new Money())->MoneyEdit($money2, 0, $coinnum, 3, '项目兑换', 0, 0);
                (new Myprelist())->insert([
                    'preid' => $result['id'],
                    'codeid' => $code['id'],
                    'user_id' => $user['id'],
                    'num' => $coinnum,
                    'havenum' => $data['num'],
                    'coin' => $result['coin'],
                    'havecoin' => $data['cointype'],
                    'price' => $price,
                    'haveprice' => $price1
                ]);
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                dump($e->getMessage());
                Db::rollback();
                $this->result([], 1, '参与失败，请稍后重试');
            }
            $this->result([], 0, '参与成功');
        } else {
            $id = $this->request->get('id/d', 0);
            $coins = Configs::get('config.coins');
            $list = (new Myprelist())->order('id desc');
            if ($id) {
                $list = $list->where('preid', $id);
            }
            $list = $list->where('user_id', $this->request->user_id)->field('num,havenum,created,coin,havecoin')->paginate(20, false, ['query' => $this->request->param()]);
            foreach ($list as $lists) {
                $lists['coin_name'] = $coins[$lists['coin']];
                $lists['havecoin_name'] = $coins[$lists['havecoin']];
            }
            $this->result($list, 0, '获取成功');
        }
    }

    public function getaddress()
    {
        $type = $this->request->get('type/d', '');
        if (empty($type)) {
            $this->result([], 1, '类型错误');
        }
        $coin = Configs::get('config.coins.' . $type);
        if (empty($coin)) {
            $this->result([], 1, '币种错误');
        }
        $user_id = $this->request->user_id;
        //查询类型是否存在
        $wallet = (new Wallet())->field('address')->where(['type' => $type, 'user_id' => $user_id])->find();
        if (empty($wallet)) {
            if ($coin == 'BTC') {
                $data = (new Btc())->create();
                $private = rand(1000, 9999) . 'B' . $data['privateKey'];
                if (strlen($private) < 57) {
                    $this->result([], 1, '生成错误请重试');
                }
                (new Wallet())->insert([
                    'user_id' => $user_id,
                    'type' => $type,
                    'address' => $data['p2pkh'],
                    'private' => $private,
                    'created' => date('Y-m-d H:i:s')
                ]);
                $wallet = (new Wallet())->field('address')->where(['type' => $type, 'user_id' => $user_id])->find();
            } elseif ($coin == 'ETH') {
                $data = (new ETH())->wallet();
                $private = rand(1000, 9999) . 'E' . $data['private'];
                if (strlen($private) < 68) {
                    $this->result([], 1, '生成错误请重试');
                }
                (new Wallet())->insert([
                    'user_id' => $this->request->user_id,
                    'type' => $type,
                    'address' => $data['address'],
                    'private' => $private,
                ]);
                $wallet = (new Wallet())->field('address')->where(['type' => $type, 'user_id' => $user_id])->find();
            } elseif ($coin == 'USDT' || $type == 1) {
                $wallet = (new Wallet())->field('address,private')->where(['type' => 3, 'user_id' => $user_id])->find();
                if (empty($wallet)) {
                    $data = (new ETH())->wallet();
                    $private = rand(1000, 9999) . 'E' . $data['private'];
                    if (strlen($private) < 68) {
                        $this->result([], 1, '生成错误请重试');
                    }
                    (new Wallet())->insert([
                        'user_id' => $this->request->user_id,
                        'type' => 3,
                        'address' => $data['address'],
                        'private' => $private,
                    ]);
                    (new Wallet())->insert([
                        'user_id' => $this->request->user_id,
                        'type' => $type,
                        'address' => $data['address'],
                        'private' => $private,
                    ]);
                } else {
                    (new Wallet())->insert([
                        'user_id' => $this->request->user_id,
                        'type' => $type,
                        'address' => $wallet['address'],
                        'private' => $wallet['private'],
                    ]);
                }
                $wallet = (new Wallet())->field('address')->where(['type' => $type, 'user_id' => $user_id])->find();
            }
        }
        $this->result($wallet, 0, '获取成功');
    }


    public function Recharge()
    {
        $user_id = $this->request->user_id;
        $rechargerds = 'recharge' . $user_id;
        if (!Redis::get($rechargerds)) {
            Redis::setex($rechargerds, 5, $user_id);
            //进行充值查询
            $ethkeys = '9D8KX5N8TR55M2F86IR4EEKCKVZH21FY95';
            $wallet = (new Wallet())->where('user_id', $user_id)->select();
            foreach ($wallet as $wallets) {
                $coin = Configs::get('config.coins.' . $wallets['type']); //币种类型
                //btc充值
                if ($coin == 'BTC') {
                    $rechargeM = 0;
                    $url = 'https://blockchain.info/q/addressbalance/' . $wallets['address'];
                    $resulturl = api_curl($url);
                    $result = json_decode($resulturl, true);
                    if (!empty($result) && $result > 0 && ($result / pow(10, 8) - $wallets['money']) > 0.0001) {
                        $rechargeM = $money / pow(10, 8) - $wallets['money'];
                        $moneys = (new Money())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->find();
                        Db::startTrans();
                        try {
                            (new Money())->MoneyEdit($moneys, 0, $rechargeM, 4, '币种自动充值', 0, 0);
                            (new Wallet())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->setInc('money', $rechargeM);
                            Db::commit();
                        } catch (\Exception $exception) {
                            echo $exception->getMessage();
                            Db::rollback();
                        }
                        echo $coin . '查询到账' . $rechargeM . '个' . '\n';
                    }
                } elseif ($coin == 'ETH') {
                    $rechargeM = 0;
                    $url = 'http://api.etherscan.io/api?module=account&action=balance&address=' . $wallets['address'] . '&tag=latest&apikey=' . $ethkeys;
                    $resulturl = api_curl($url);
                    $result = json_decode($resulturl, true);
                    if (!empty($result) && $result['status'] == 1 && $result['result'] > 0 && ($result['result'] / pow(10, 18) - $wallets['money']) >= 0.0001) {
                        $rechargeM = $result['result'] / pow(10, 18) - $wallets['money'];
                        $moneys = (new Money())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->find();
                        Db::startTrans();
                        try {
                            (new Wallet())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->setInc('money', $rechargeM);
                            (new Money())->MoneyEdit($moneys, 0, $rechargeM, 4, '币种自动充值', 0, 0);
                            Db::commit();
                        } catch (\Exception $exception) {
                            echo $exception->getMessage();
                            Db::rollback();
                        }
                        echo $coin . '查询到账' . $rechargeM . '个' . '\n';
                    }
                } elseif ($coin == 'USDT') {
                    $coinlength = 18;
                    $contact = '0xdac17f958d2ee523a2206206994597c13d831ec7';
                    $coinlength = 6;
                    $rechargeM = 0;
                    $url = 'http://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=' . $contact . '&address=' . $wallets['address'] . '&tag=latest&apikey=' . $ethkeys;
                    $resulturl = api_curl($url);
                    $result = json_decode($resulturl, true);
                    if (!empty($result) && $result['status'] == 1 && $result['result'] > 0 && ($result['result'] / pow(10, $coinlength) - $wallets['money']) > 0.0001) {
                        $rechargeM = $result['result'] / pow(10, $coinlength) - $wallets['money'];
                        $moneys = (new Money())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->find();
                        Db::startTrans();
                        try {
                            (new Wallet())->where(['user_id' => $wallets['user_id'], 'type' => $wallets['type']])->setInc('money', $rechargeM);
                            (new Money())->MoneyEdit($moneys, 0, $rechargeM, 4, '币种自动充值', 0, 0);
                            Db::commit();
                        } catch (\Exception $exception) {
                            echo $exception->getMessage();
                            Db::rollback();
                        }
                        echo $coin . '查询到账' . $rechargeM . '个' . '\n';
                    }
                }
            }
        }
        $this->result([], 0, '查询完成');
    }

    public function Rechargelist()
    {
        $list = [];
        $coin = Configs::get('config.coins');
        foreach ($coin as $k => $coins) {
            if ($coins == 'USDT') {
                $list[] = [
                    'name' => $coins,
                    'type' => $k,
                    'remake' => 'ERC20'
                ];
            }
            if ($coins == 'BTC' || $coins == 'ETH') {
                $list[] = [
                    'name' => $coins,
                    'type' => $k,
                    'remake' => ''
                ];
            }
        }
        $this->result($list, 0, '获取成功');
    }

    public function moneylog()
    {
        $type = $this->request->get('type/d', 0);
        $cointype = $this->request->get('cointype/d', 0);
        $coins = Configs::get('config.coins');
        $list = (new Moneylog())->order('id desc');
        if ($type) {
            $list = $list->where('type', $type);
        }
        if ($cointype) {
            $list = $list->where('cointype', $cointype);
        }
        $language = !empty($GLOBALS['_SERVER']['HTTP_LANGUAGE']) ? $GLOBALS['_SERVER']['HTTP_LANGUAGE'] : 'cn';
        $typeconfig = Configs::get('language.' . $language)['moneytype'] ?? [];
        $list = $list->where('user_id', $this->request->user_id)->field('money,created,type,cointype')->paginate(20, false, ['query' => $this->request->param()]);
        foreach ($list as $lists) {
            $lists['coin_name'] = $coins[$lists['cointype']];
            $lists['type_name'] = $typeconfig[$lists['type']] ?? '';
        }
        $this->result($list, 0, '获取成功');
    }

    public function moneytype()
    {
        $language = !empty($GLOBALS['_SERVER']['HTTP_LANGUAGE']) ? $GLOBALS['_SERVER']['HTTP_LANGUAGE'] : 'cn';
        $config = Configs::get('language.' . $language)['moneytype'] ?? [];
        $result = [];
        foreach ($config as $k => $types) {
            $result[] = [
                'type' => $k,
                'type_name' => $types
            ];
        }
        $this->result($result, 0, '获取成功');
    }


    public function Withdraw()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            $validate = new Validate([
                'cointype' => 'require',
                'coinnum' => 'require|gt:0|float',
                'address' => 'require',
                'trade' => 'require'
            ], [
                'cointype.require' => '币种类型不能为空',
                'coinnum.require' => '币种数量不能为空',
                'coinnum.gt' => '币种数量必须大于0',
                'coinnum.float' => '币种数量必须是数字',
                'address.require' => '提币地址不能为空',
                'trade.require' => '交易密码不能为空'
            ]);
            if (!$validate->check($data)) {
                $this->result([], 1, $validate->getError());
            }
            $user = $this->request->user;
            $coin = Configs::get('config.coins.' . $data['cointype']) ?? '';
            if ($coin != 'BTC' && !(preg_match('/^(0x)?[0-9a-fA-F]{40}$/', $data['address']))) {
                $this->result([], 1, '请输入正确的提币地址');
            }
            // BTC地址合法校验
            if ($coin == 'BTC' && !(preg_match('/^(1|3)[a-zA-Z\d]{24,33}$/', $data['address']) && preg_match('/^[^0OlI]{25,34}$/', $data['address']))) {
                $this->result([], 1, '请输入正确的提币地址');
            }
            if ($coin == 'USDT') {
                $handfee = (new Config())->where('key_value', 'otherhandfee')->value('value'); //匹配价格幅度范围
            } elseif ($coin == 'ETH') {
                $handfee = (new Config())->where('key_value', 'ethotherhandfee')->value('value'); //匹配价格幅度范围
            } elseif ($coin == 'BTC') {
                $handfee = (new Config())->where('key_value', 'btcotherhandfee')->value('value'); //匹配价格幅度范围
            } else {
                $this->result([], 1, '类型错误');
            }
            if (empty($handfee)) {
                $this->result([], 1, '手续费未设置，请联系管理员');
            }
            $handfee = json_decode($handfee, true);
            if (empty($handfee)) {
                $this->result([], 1, '手续费设置出错，请联系管理员');
            }
            $fee = 0;
            if ($data['coinnum'] < $handfee['coinnum']) {
                $this->result([], 1, '提币数量不能低于' . $handfee['coinnum']);
            }
            $fee = round($data['coinnum'] * $handfee['coinhandfee'] / 100, 4);
            $price = (new Price())->where('dates', '<=', date('Y-m-d'))->where(['coin' => $data['cointype'], 'mart' => 2, 'istrue' => 1])->order('dates desc')->value('price');
            $price = $price ? $price : 0;
            if ($user['trade'] != md5(md5($data['trade']))) {
                $this->result([], 1, '交易密码错误');
            }
            //判断币种数量是否足够
            $usermoney = (new Money())->where(['user_id' => $user['id'], 'type' => $data['cointype']])->find();
            if (empty($usermoney)) {
                $this->result([], 1, '钱包不存在');
            }
            $data['coinnum'] = floor($data['coinnum'] * 10000) / 10000;
            if ($usermoney['money'] < $data['coinnum']) {
                $this->result([], 1, '币种数目不足');
            }
            Db::startTrans();
            try {
                (new Money())->MoneyEdit($usermoney, 0, -$data['coinnum'], 5, '用户提现', 0, 0);
                (new Withdraw())->insert([
                    'user_id' => $user['id'],
                    'cointype' => $data['cointype'],
                    'coinnum' => $data['coinnum'],
                    'handfee' => $fee,
                    'dates' => date('Y-m-d'),
                    'address' => $data['address'],
                    'price' => $price
                ]);
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                dump($e->getMessage());
                $this->result([], 1, '提现申请失败，请稍后重试');
            }
            $this->result([], 0, '提现申请成功');
        } else {
            $data = $this->request->get();
            $validate = new Validate([
                'cointype' => 'require',
                'coinnum' => 'require'
            ], [
                'cointype.require' => '币种类型不能为空',
                'coinnum.require' => '币种数量不能为空',
            ]);
            if (!$validate->check($data)) {
                $this->result([], 1, $validate->getError());
            }
            $coin = Configs::get('config.coins.' . $data['cointype']) ?? '';
            if ($coin == 'USDT') {
                $handfee = (new Config())->where('key_value', 'otherhandfee')->value('value'); //匹配价格幅度范围
            } elseif ($coin == 'ETH') {
                $handfee = (new Config())->where('key_value', 'ethotherhandfee')->value('value'); //匹配价格幅度范围
            } elseif ($coin == 'BTC') {
                $handfee = (new Config())->where('key_value', 'btcotherhandfee')->value('value'); //匹配价格幅度范围
            } else {
                $this->result([], 1, '类型错误');
            }
            if (empty($handfee)) {
                $this->result([], 1, '查询失败');
            }
            $handfee = json_decode($handfee, true);
            if (empty($handfee)) {
                $this->result([], 1, '查询失败');
            }
            $fee = 0;
            $data['fee'] = round($data['coinnum'] * $handfee['coinhandfee'] / 100, 4);
            $data['min'] = $handfee['coinnum'];
            $this->result($data, 0, '查询完成');
        }
    }

    public function Withdrawlist()
    {
        $data = $this->request->get();
        $list = (new Withdraw())->order('id desc');
        if (!empty($data['cointype'])) {
            $list = $list->where('cointype', $data['cointype']);
        }
        $language = !empty($GLOBALS['_SERVER']['HTTP_LANGUAGE']) ? $GLOBALS['_SERVER']['HTTP_LANGUAGE'] : 'cn';
        $config = Configs::get('language.' . $language)['widthstatus'] ?? [];
        $list = $list->where(['user_id' =>  $this->request->user_id, 'type' => 1])
            ->field('coinnum,cointype,handfee,address,status,hash,created')
            ->paginate(20, false, ['query' => $this->request->param()])->each(function ($result) use ($config) {
                $result['coinname'] =  Configs::get('config.coins.' . $result['cointype']);
                $result['statustext'] = $config[$result['status']] ?? '';
                return $result;
            });
        $this->result($list, 0, '查询完成');
    }
}
